home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume4 / curses-widgets < prev    next >
Encoding:
Text File  |  1989-02-03  |  56.2 KB  |  2,155 lines

  1. Path: xanth!nic.MR.NET!hal!ncoast!allbery
  2. From: rac@gec-rl-hrc.co.uk (rac)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i131: curses-based widget library and dem.
  5. Keywords: curses, widget.
  6. Message-ID: <537@hrc63.co.uk>
  7. Date: 22 Oct 88 01:31:21 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Reply-To: rac@gec-rl-hrc.co.uk (rac)
  10. Organization: GEC Hirst Research Centre, Wembley, England.
  11. Lines: 2129
  12. Approved: allbery@ncoast.UUCP
  13.  
  14. Posting-number: Volume 4, Issue 131
  15. Submitted-by: "rac" <rac@gec-rl-hrc.co.uk>
  16. Archive-name: curses-widgets
  17.  
  18. --------------------------- CUT HERE ------------------------------
  19. #! /bin/sh
  20. # This is a shell archive. To extract the files type 'sh file'
  21. # This archive created on Fri Oct 14 13:28:51 BST 1988
  22.  
  23. export PATH; PATH=/bin:$PATH
  24. echo 'Shar: extracting 'README' ( 1974 characters)'
  25. if test -f 'README'
  26. then
  27.     echo "Shar: will not overwrite existing file 'README'"
  28. else
  29.     cat << \SHAR_EOF > 'README'
  30. /*****************************************************************************
  31. /*  FILE:        README
  32. /*  DATE:        August 1988.
  33. /*  AUTHOR:        Richard A. Culshaw.
  34. /* DISCLAIMER:        This file is deemed to be public-domain, on the simple
  35. /*            provisos that this section remains in this file and
  36. /*            that code using it do not do so for monetary gain.
  37. /*            Neither the author, nor the authors employees at the
  38. /*            time of developing this code, accept any liability or
  39. /*            responsibility for the use, abuse or misuse of this
  40. /*            code.
  41. /*****************************************************************************/
  42.  
  43.     Widgetlib is a standard C library which allows the user to define
  44. and interact with widgets (window gadget). The files provided are:
  45.  
  46. -rw-r--r--   1 pjs      net         1960 Oct 14 13:25 README
  47. -rw-r--r--   1 pjs      net         1144 Oct 14 13:23 makefile
  48. -rw-r--r--   1 pjs      net         2752 Oct 14 13:15 widget.h
  49. -rw-r--r--   1 pjs      net        10946 Oct 14 12:18 widget.ms
  50. -rw-r--r--   1 pjs      net        34817 Oct 14 13:15 widgetlib.c
  51. -rw-r--r--   1 pjs      net         3218 Oct 14 13:14 wpage.c
  52.  
  53. 1) widgetlib.c       (the actual code)
  54. 2) widget.h         (the header file which is needed in programs intending
  55.               to incorporate the library)
  56. 3) widget.ms         (an explanation of the library and how to use it)
  57. 4) wpage.c         (a little example of the library in use)
  58. 5) makefile          (compiles everything together)
  59.  
  60. Compiling things
  61. ================
  62.  
  63. Type 'make' within the directory which contains the files.
  64. This creates a local library within the directory, and creates the 
  65. executable 'wpage' (a demo for you to play with).
  66.  
  67. For general use 'widget.h' must be placed in the standard include directory
  68. and the library 'widgetlib.a' must go in a globally accessable place such
  69. as /usr/lib.
  70.  
  71. Printing doc
  72. ============
  73.  
  74. 'widget.ms' was created using the ms macros and can printed using something like
  75. 'nroff -ms widget.ms'
  76.  
  77.  
  78. Have fun. Richard C.
  79. SHAR_EOF
  80. if test 1974 -ne `wc -c < 'README'`
  81. then
  82.     echo 'Shar: error transmitting 'README' (should have been  1974 charcaters)'
  83. fi
  84. fi
  85. echo 'Shar: extracting 'makefile' ( 1144 characters)'
  86. if test -f 'makefile'
  87. then
  88.     echo "Shar: will not overwrite existing file 'makefile'"
  89. else
  90.     cat << \SHAR_EOF > 'makefile'
  91. /*****************************************************************************
  92. /*  FILE:        makefile
  93. /*  DATE:        August 1988.
  94. /*  AUTHOR:        Richard A. Culshaw.
  95. /* DISCLAIMER:        This file is deemed to be public-domain, on the simple
  96. /*            provisos that this section remains in this file and
  97. /*            that code using it do not do so for monetary gain.
  98. /*            Neither the author, nor the authors employees at the
  99. /*            time of developing this code, accept any liability or
  100. /*            responsibility for the use, abuse or misuse of this
  101. /*            code.
  102. /*****************************************************************************/
  103.  
  104. # Use -g if you want large, but sdb-,gdb-,dbx-able objects.
  105. OPTIONS= -O
  106.  
  107. # BSD systems, in particular, will want -lcurses -ltermcap.
  108. CURSES=  -lcurses
  109.  
  110. # SYS5 systems, in particular, do not have ranlib(1) for their libraries.
  111. # So define this as, for example, touch, if you don't have ranlib.
  112. RANLIB= touch
  113.  
  114. WDGTLIB= widgetlib.a
  115.  
  116. all: wpage
  117.  
  118. widgetlib.a: widgetlib.o widget.h
  119.     ar crv $@ widgetlib.o
  120.     ${RANLIB} $@
  121.     rm -f widgetlib.o
  122.  
  123. wpage: widgetlib.a wpage.o
  124.     cc ${OPTION} -o $@ wpage.o ${WDGTLIB} ${CURSES}
  125.  
  126. clean:
  127.     rm -f wpage *.o *.a
  128. SHAR_EOF
  129. if test 1144 -ne `wc -c < 'makefile'`
  130. then
  131.     echo 'Shar: error transmitting 'makefile' (should have been  1144 charcaters)'
  132. fi
  133. fi
  134. echo 'Shar: extracting 'widget.h' ( 2752 characters)'
  135. if test -f 'widget.h'
  136. then
  137.     echo "Shar: will not overwrite existing file 'widget.h'"
  138. else
  139.     cat << \SHAR_EOF > 'widget.h'
  140. /*****************************************************************************
  141. /*  FILE:        widget.h
  142. /*  DATE:        August 1988.
  143. /*  AUTHOR:        Richard A. Culshaw.
  144. /*  DESCRIPTION:    Contains the definitions of the widget structures.
  145. /*            It should be included by all programs that want to
  146. /*            use the widget library.
  147. /* DISCLAIMER:        This file is deemed to be public-domain, on the simple
  148. /*            provisos that this section remains in this file and
  149. /*            that code using it do not do so for monetary gain.
  150. /*            Neither the author, nor the authors employees at the
  151. /*            time of developing this code, accept any liability or
  152. /*            responsibility for the use, abuse or misuse of this
  153. /*            code.
  154. /*****************************************************************************/
  155.  
  156. #include <curses.h>
  157.  
  158. /* definition for command widget entry in linked list */
  159. struct    cmdwid{
  160.             WINDOW        *widget;
  161.             int        id;
  162.             char        msg[100];
  163.             char        acpt;
  164.             int        (*func)();
  165.             int        length;    
  166.             int        x,y;
  167.         int        active;
  168.             struct cmdwid    *next;
  169.         } *cmdlist;
  170.  
  171. /* definition for label widget entry in linked list */
  172. struct    lblwid{
  173.             WINDOW        *widget;
  174.             int        id;
  175.             char        msg[100];
  176.             char        pos;
  177.             int        length;    
  178.         int        difference;
  179.             int        x,y;
  180.             struct lblwid    *next;
  181.         } *lbllist;
  182.  
  183. /* definition for togle widget entry in linked list */
  184. struct     tglwid{
  185.             WINDOW        *widget;
  186.             int        id;
  187.             char        msg[100];
  188.             char        tgl[10][20];
  189.             char        toggle;
  190.             int        cur;
  191.          int         total;
  192.             int        length;
  193.             int         xtgl;
  194.             int        x,y;
  195.         int        active;
  196.             struct tglwid    *next;
  197.         } *tgllist;
  198.  
  199. /* definition for input widget entry in linked list */
  200. struct inpwid{
  201.             WINDOW        *widget;
  202.             int         id;
  203.         char        msg[100];
  204.             char        acpt;
  205.             char        *input;
  206.         int        sofi;
  207.         int        exec;
  208.             int        lofs;
  209.             int        length;
  210.             int        x,y;
  211.         int        active;
  212.             struct inpwid    *next;
  213.         } *inplist;
  214.     
  215. /* linked list of characters used for activating widgets */    
  216. struct chentry {
  217.             char          ch;
  218.             int           type;
  219.             int          id;
  220.         struct chentry    *next;
  221.         } *actlist;
  222.  
  223. /* null entries in the various linked list */
  224. #define NULLCMD        (struct cmdwid *)NULL
  225. #define NULLLBL     (struct lblwid *)NULL
  226. #define NULLTGL     (struct tglwid *)NULL
  227. #define NULLINP     (struct inpwid *)NULL
  228. #define NULLCH         (struct chentry *)NULL
  229.  
  230. /* part of the specifications for label widgets */
  231. #define CENTRE        1
  232. #define    LEFTJUST    2
  233. #define RIGHTJUST    4
  234. #define NOHIGH        8
  235.  
  236. /* the types of the widgets */
  237. #define CMD        1
  238. #define TGL        2
  239. #define LBL        3
  240. #define INP        4
  241.  
  242. #define BLANK        1
  243. #define NOBLANK        0
  244.  
  245. #define NULLWIDGET    0
  246.  
  247. #define EXEC        1
  248. #define NOEXEC        0
  249.  
  250. #define VERTICAL    1
  251. #define HORIZONTAL    2
  252.  
  253. typedef int WIDGET;
  254. typedef int WIDGETTYPE;
  255.  
  256. SHAR_EOF
  257. if test 2752 -ne `wc -c < 'widget.h'`
  258. then
  259.     echo 'Shar: error transmitting 'widget.h' (should have been  2752 charcaters)'
  260. fi
  261. fi
  262. echo 'Shar: extracting 'widget.ms' ( 10946 characters)'
  263. if test -f 'widget.ms'
  264. then
  265.     echo "Shar: will not overwrite existing file 'widget.ms'"
  266. else
  267.     cat << \SHAR_EOF > 'widget.ms'
  268. .ND
  269. .LP
  270. .nr PS 12
  271. .nr VS 13
  272. .LP
  273. .nh
  274. .RP
  275. .TL
  276. A Window based Interactive Programming Utility On Unix:
  277. A Library Package for C programmers
  278. .AU
  279. Richard A. Culshaw
  280. .AI
  281. GEC Hirst Research Centre
  282. Data Systems Division
  283. East Lane
  284. Wembley
  285. Middlesex HA9 7PP
  286. .ND
  287. .KS
  288. .SH
  289. INTRODUCTION
  290.  
  291. .PP
  292. A Widget is a user definable 
  293. .B "window gadget."
  294.  They allow the user to interact with the program in specifying operations to be carried out. Widgetlib is a set of library functions which allows the user to create and interact with 
  295. .B widgets.
  296. A widget can be one of four types :
  297. .LP
  298.       1) 
  299. .B Command 
  300. Widget 
  301.       2) 
  302. .B Label 
  303. Widget
  304.       3) 
  305. .B Toggle 
  306. Widget
  307.       4) 
  308. .B Input 
  309. Widget
  310.  
  311. .SH
  312. Command Widgets
  313. .PP
  314. A command widget allows the user to select a function to be carried out, e.g in a paging program one such command could be 'Next Page'. In creating a command widget the programmer must pass it the function to be carried out when the widget is selected (activated). The widget is activated using a unique 'activation' character which is displayed in the widget for easy reference.
  315.  
  316. .SH
  317. Label Widgets
  318. .PP
  319. A label widget is simply a widget which holds a character string such as a heading, which can be changed at will later. The programmer can supply parameters which can either left justify (default), right justify, or centre the message within the widget (which has a user definable width) as well as highlight (default) or dehighlight it.
  320.  
  321. .SH
  322. Toggle Widgets
  323. .PP
  324. A toggle widget contains a message which indicates the current value of an entity which can be more than one value e.g, Yes/No/Don't-Know. The value is toggled when a given character is pressed. The activation character is also displayed in the widget. At any point the programmer can enquire as to the the current toggle value.
  325.  
  326. .SH
  327. Input Widgets
  328. .PP
  329. An input widget allows the user to enter information into the program in the form of a string, e.g in a paging program one might want to supply a file name. There are two types of input widgets :
  330.  
  331. a) The widget is activated immediately on creation therefore an activation character is not required. E.g in a paging program one might have a command widget which activates this type of input widget in order to get a file name.
  332. .LP
  333. b) The widget has an associated activation character so therefore it may be activated at any point after creation. The character is displayed in the widget.
  334.  
  335. For ease of use the input widgets contain character strings which can explain
  336. there use within the program.
  337. .KE
  338. .bp
  339. .SH
  340. Text Window
  341. .PP
  342. The library also allows the user to define a text window into which the program may report information. On creation the program has to pass a parameter which specifies how much room to leave before the top of the text window. E.g 0 means place the window immediately below the lowest widget, 1 means allow room for one more row of widgets before placing the window. The text window always stretches to the bottom of the screen. The window can be bordered on any 2 opposite sides or on all 4 (effectively boxing 
  343.  
  344. it).
  345.  
  346. .SH
  347. Widget Placement
  348. .PP
  349. The library maintains the current X,Y coordinate of the last widget created. When a new widget is created the program must pass a parameter 0 or 1. A 0 means put the new widget on the current row if possible, else go onto the next row. A 1 forces the new widget onto the next row. This means that widgets can only go after preceding ones and not before. But however widgets can be placed over widgets which have previously been destroyed.
  350.  
  351. .SH
  352. Compiling Things
  353. .PP
  354. In order to use the library, it is necessary to have certain types and variables defined. Therefore, the program must have the line:
  355. .PP
  356. .B "#include <widgets.h>"
  357. .LP
  358. at the top of the source. The header file includes <curses.h>, <sgetty.h>, <stdio.h> so you don't have to include them also. Also compilations should have the following form:
  359. .PP
  360. .B "cc [flags] file ... -lwidgets -lcurses"
  361.  
  362. .SH
  363. Type Definitions
  364. .LP
  365. The functions which create widgets return a type 
  366. .B WIDGET
  367. which is used for later identification of the widget.
  368. .LP
  369. If a function is required to return a widget identifier, then it will return 
  370. .B NULLWIDGET
  371. upon error.
  372.  
  373. .SH
  374. Screen Refresh
  375. .LP
  376. The library supports a standard screen refresh invoked by ^L.
  377. .KE
  378. .bp
  379. .KS
  380. .SH
  381.                                               USAGE
  382. .SH
  383. Getting Started
  384. .LP
  385. The first thing to do when using the library is set up the windowing system by calling 
  386. .LP
  387. .in 0.5i
  388. initialisewidgets()
  389. .in 0
  390.  
  391. .SH
  392. Creating Widgets
  393. .LP
  394. .br
  395.  
  396. .in 0.5i
  397. WIDGET mkcmdwidget (message, ch, function, row)
  398. .br 
  399. char message[];
  400. .br 
  401. char ch;
  402. .br 
  403. int 
  404. (*func)();
  405. .br 
  406. int line;
  407. .in 0
  408. .LP
  409. Creates a new command widget. message holds the message to be displayed in the command widget. ch is the activation character on which function is executed. row specifies where to place the widget (as described above). The returned value is the widget identifier for later use.
  410.  
  411. .LP
  412. .in 0.5i
  413. WIDGET mklblwidget (message, position, space, row)
  414. .br
  415. char message[];
  416. .br
  417. int  position, space, row;
  418. .in 0
  419. .LP
  420. Creates a new label widget. Message holds the contents of the label, position specifies how the message is to appear. Using the constants CENTRE, LEFTJUST, RIGHTJUST, NOHIGH, pass a combination to position e.g CENTRE or LEFTJUST|NOHIGH etc.space indicates how large the label widget is to be. A positive value is the absolute length of the widget, whereas value <= 0 specifies how far the widget is to be from the righthand edge of the screen. row specifies where to place the widget (as described above). The r
  421.  
  422. eturned value is the widget identifier for later use.
  423.  
  424. .LP
  425. .in 0.5i
  426. WIDGET mktglwidget (message, number, tgl, tglch, row)
  427. .br
  428. char message[];
  429. .br
  430. int  number;
  431. .br
  432. char tgl[10][20];
  433. .br
  434. char tglch;
  435. .br
  436. int  row;
  437. .in 0
  438. .LP
  439. Creates a new toggle widget. message contains a label for the widget, and number holds the number of toggle values. tgl is used for holding actual toggle values which are toggled between using the activation character tglch. At present there is a limit of 10 toggle values, each being a maximum length of 20 characters. row specifies where to place the widget (as described above). The returned value is the widget identifier for later use.
  440. .LP
  441. .KE
  442. .bp
  443. .KS
  444. .in 0.5i
  445. WIDGET mkinpwidget (message, character, input, lengthstr, lengthwid, row, exec)
  446. .br
  447. char message[], character, input[];
  448. .br
  449. int  lengthstr, lengthwid, row, exec; 
  450. .in 0
  451. .LP
  452. Creates a new input widget. message contains the label for the widget, and character is the activation character for the widget. input is the variable in which the user wishes the data obtained from the input widget to be placed, lengthstr is the length of input. lengthwid specifies how big to make the widget. A positive value indicates the absolute length of the widget, where as a value <= 0 indicates how far from the righthand edge the widget is to be. exec is used to indicate whether the widget should b
  453.  
  454. e activated on creation by (passing EXEC), or should remain dormant until the activation character is used (passing NOEXEC). (n.b when passing EXEC an activation character is not needed therefore one could pass NULL for character.)
  455.  
  456. .SH
  457. Text Window Management
  458. .LP
  459. .br
  460.  
  461. .in 0.5i
  462. int opentextwindow (position, border)
  463. .br
  464. int position, border;
  465. .in 0
  466. .LP
  467. Opens and displays the text window. position specifies where the window is to go. i.e position = 0 will place the window immediately below the lowest widget, position = 1 will allow room for 1 more row of widgets below the current lowest before placing the window etc. border is used to indicate whether the window should be bordered. i.e using the parameters VERTICAL & HORIZONTAL, one can specify whether the window should be bordered vertically (passing VERTICAL), horizontally (passing HORIZONTAL), both (pa
  468.  
  469. ssing VERTICAL|HORIZONTAL), or neither (passing 0). The function returns the number of lines within the window.
  470.  
  471. .in 0.5i
  472. report (message)
  473. .br
  474. char *message;
  475. .in 0
  476. .LP
  477. Displays the given message in the text window. Scrolling is done automatically when the bottom of the window is reached and is therefore of no concern for the user.
  478.  
  479. .in 0.5i
  480. cleartextwindow ()
  481. .in 0
  482. .LP
  483. Clears the text window and returns its cursor to the top lefthand corner. 
  484.  
  485. .in 0.5i
  486. killtextwindow ()
  487. .in 0
  488. .LP
  489. Destroys the text window. The text window can be redefined at a later date.
  490.  
  491. .SH
  492. Killing Widgets
  493.  
  494. .LP
  495. .br
  496. .in 0.5i
  497. int killwidget (ptr)
  498. .br
  499. WIDGET ptr;
  500. .in 0
  501. .LP
  502. Kills the given widget. the function returns TRUE if successfull or FALSE if the widget doesn't exist.
  503. .KE
  504. .bp
  505. .KS
  506. .SH
  507. Interaction
  508.  
  509. .LP
  510. .br
  511. .in 0.5i
  512. WIDGET widgetinput ()
  513. .in 0
  514. .LP
  515. Wait for input from widgets. Program control is passed back when :-
  516. .br
  517. a) A Command widget is activated and control is passed to its associated function.
  518. .br
  519. b) An input widget is activated and after subsequent input, control is passed to the calling function with the widget pointer of the activated input widget.
  520. .br
  521. Activating a toggle widget just toggles the widget, control is only passed back upon one of the above conditions.
  522.  
  523. .LP
  524. .br
  525. .in 0.5i
  526. int tsttglwidget (ptr)
  527. .br
  528. WIDGET ptr;
  529. .in 0
  530. .LP
  531. Returns the index value of the current state of the given toggle widget (0 < index < number toggle values - 1). Returns FALSE if the given widget does not exist.
  532.  
  533. .LP
  534. .br
  535. .in 0.5i
  536. int activate (ptr)
  537. .br
  538. WIDGET ptr;
  539. .in 0
  540. .LP
  541. Reactivates a widget which was previously deactivated. Returns TRUE if successful otherwise FALSE.
  542.  
  543. .LP
  544. .br
  545. .in 0.5i
  546. int deactivate (ptr, blank)
  547. .br
  548. WIDGET ptr;
  549. .br
  550. int    blank;
  551. .in 0
  552. .LP
  553. Deactivates the given active widget. The widget remains on screen but it cannot be activated. blank can be BLANK or NOBLANK which indicates whether the contents of the widget should be blanked out or not while it is inactive. The function returns TRUE if successful or FALSE if the given widget does not exist.
  554.  
  555. .LP
  556. .br
  557. .in 0.5i
  558. int highlight (ptr)
  559. .br
  560. WIDGET ptr;
  561. .in 0
  562. .LP
  563. Highlights the given widget. Returns TRUE if successful else FALSE if the widget does not exist.
  564.  
  565. .LP
  566. .br
  567. .in 0.5i
  568. int dehighlight (ptr)
  569. .br
  570. WIDGET ptr;
  571. .in 0
  572. .LP
  573. Turns off the highlighting of the given widget. Returns TRUE if successful else FALSE if the widget does not exist.
  574.  
  575. .LP
  576. .br
  577. .in 0.5i
  578. int changelblwidget (ptr, message, position)
  579. .br
  580. WIDGET ptr;
  581. .br
  582. char   message[];
  583. .br
  584. int    position;
  585. .in 0
  586. .LP
  587. Changes the contents of the given label widget to that given in message. position specifies how the message is to appear (see mklblwidget). The function returns TRUE if successful else FALSE.
  588. .KE
  589. .KS
  590. .LP
  591. .br
  592. .in 0.5i
  593. WIDGETTYPE widgettype (ptr)
  594. .br
  595. WIDGET ptr;
  596. .in 0
  597. .LP
  598. Returns the type of widget pointed too by ptr. The returned type value is one of CMD, LBL, TGL, INP or FALSE if the widget does not exist.
  599.  
  600. .SH
  601. Finishing Up
  602.  
  603. .LP
  604. .br
  605. .in 0.5i
  606. endwidgets ()
  607. .in 0
  608. .LP
  609. Closes down the windowing system and should be used at the end. This function is also automatically called on an interrupt (e.g ^C).
  610. .KE
  611. SHAR_EOF
  612. if test 10946 -ne `wc -c < 'widget.ms'`
  613. then
  614.     echo 'Shar: error transmitting 'widget.ms' (should have been  10946 charcaters)'
  615. fi
  616. fi
  617. echo 'Shar: extracting 'widgetlib.c' ( 34817 characters)'
  618. if test -f 'widgetlib.c'
  619. then
  620.     echo "Shar: will not overwrite existing file 'widgetlib.c'"
  621. else
  622.     cat << \SHAR_EOF > 'widgetlib.c'
  623. /*****************************************************************************
  624. /*  FILE:        widgetlib.c
  625. /*  DATE:        August 1988.
  626. /*  AUTHOR:        Richard A. Culshaw.
  627. /*  DESCRIPTION:    Contains the code to manipulate the widget structures
  628. /*            and the i/o. It forms a single library that should
  629. /*            be linked in with all code using these widgets.
  630. /* DISCLAIMER:        This file is deemed to be public-domain, on the simple
  631. /*            provisos that this section remains in this file and
  632. /*            that code using it do not do so for monetary gain.
  633. /*            Neither the author, nor the authors employees at the
  634. /*            time of developing this code, accept any liability or
  635. /*            responsibility for the use, abuse or misuse of this
  636. /*            code.
  637. /*****************************************************************************/
  638.  
  639. #include <widget.h>
  640.  
  641. extern char     *malloc();
  642. int        textwindowdefined = FALSE;
  643. int            widx, widy;    
  644. int        maxwidy;
  645. int            scry;
  646. int            curid;
  647. int        sizescreg;
  648. int        screenborder = 0;
  649.  
  650. WINDOW    *screen;
  651. WINDOW    *screenbox;
  652. WINDOW    *edge1;
  653. WINDOW      *edge2;
  654.  
  655.  
  656. initialisewidgets ()
  657. /* sets up screen and initialises global variables */
  658. {
  659.     int i, endwidgets();
  660.  
  661.     widx = widy = scry = 0;
  662.     curid = 1;
  663.     maxwidy = LINES - 3;
  664.     initscr ();
  665.     crmode ();
  666.     noecho ();
  667.     cmdlist = NULLCMD;
  668.     lbllist = NULLLBL;
  669.     tgllist = NULLTGL;
  670.     inplist = NULLINP;
  671.     actlist = NULLCH;
  672.     for (i=0; i<18; i++)
  673.     signal (i, endwidgets);
  674. }
  675.  
  676. drawtextwindow (y)
  677. /* draws the text window and draws a box around it */
  678. int y;
  679. {
  680.     int i;
  681.  
  682.     if ((screenborder & VERTICAL) && (screenborder & HORIZONTAL)) {
  683.         box (screenbox, '|', '-');
  684.         mvwaddch (screenbox, 0, 0, '.');
  685.         mvwaddch (screenbox, 0, COLS-2, '.');
  686.         mvwaddch (screenbox, LINES-y-1, 0, '`');
  687.         mvwaddch (screenbox, LINES-y-1, COLS-2, '\'');
  688.         touchwin (screenbox);
  689.         wrefresh (screenbox);
  690.     }
  691.     else if (screenborder & HORIZONTAL) {
  692.     waddstr (edge1, "-------------------------------------------------------------------------------");
  693.         waddstr (edge2, "-------------------------------------------------------------------------------");
  694.     wrefresh (edge1);
  695.     wrefresh (edge2);
  696.     }
  697.     else if (screenborder & VERTICAL) {
  698.     for (i=0; i<=sizescreg; i++) {
  699.         mvwaddch (edge1, i, 0, '|');
  700.         mvwaddch (edge2, i, 0, '|');
  701.        }
  702.     wrefresh (edge1);
  703.     wrefresh (edge2);
  704.     }
  705.     touchwin (screen);
  706.     wrefresh (screen);
  707. }
  708.  
  709. int opentextwindow (position, border)
  710. /* define the text window from current position down + position * widget depth*/
  711. int    position;
  712. int    border;
  713. {
  714.     if ((position >= 0) && (!textwindowdefined) && (widy + 3*position < 21)) {
  715.         maxwidy = widy + position * 3 + 3;
  716.     if ((border & VERTICAL) && (border & HORIZONTAL)) {
  717.             screenbox = newwin (LINES-maxwidy, COLS-1, maxwidy, 0);
  718.         screen = newwin (LINES-2-maxwidy, COLS-3, maxwidy+1, 1);
  719.         sizescreg = LINES-2-maxwidy;
  720.         }
  721.     else if (border & HORIZONTAL) {
  722.         screen = newwin (LINES-2-maxwidy, COLS-1, maxwidy+1, 0);
  723.             edge1 = newwin (1, COLS-1, maxwidy, 0);
  724.             edge2 = newwin (1, COLS-1, LINES-1, 0);
  725.         sizescreg = LINES-2-maxwidy;
  726.         }
  727.     else if (border & VERTICAL) {
  728.         screen = newwin (LINES-maxwidy, COLS-3, maxwidy, 1);
  729.         edge1 = newwin (LINES-maxwidy, 1, maxwidy, 0);
  730.         edge2 = newwin (LINES-maxwidy, 1, maxwidy, COLS-2);
  731.         sizescreg = LINES-maxwidy;
  732.         }
  733.     else {
  734.         screen = newwin (LINES-maxwidy, COLS-1, maxwidy, 0);
  735.         sizescreg = LINES-maxwidy;
  736.         }
  737.         screenborder = border;
  738.         scrollok (screen, TRUE);
  739.     drawtextwindow (maxwidy);
  740.         wmove (screen, scry, 0);
  741.     wrefresh (screen);
  742.     textwindowdefined = 1;
  743.     return sizescreg;
  744.     }
  745. }
  746.  
  747. int addtochlist (ch, id, type)
  748. /* add a new character to array of activation chars.
  749.  * returns TRUE if successful (char not already in list) else FALSE
  750.  */
  751. char           ch;
  752. int            id;
  753. WIDGETTYPE  type;    
  754. {
  755.     struct chentry  *chlist;
  756.     struct chentry  *newentry;
  757.     /* search list to see char already entered in the list */    
  758.     chlist = actlist;
  759.     if (chlist != NULLCH) {
  760.     while (chlist -> next != NULLCH) 
  761.        if (chlist -> ch == ch)
  762.         return FALSE;           /* char exists => error */
  763.         else
  764.         chlist = chlist -> next;
  765.         newentry = (struct chentry*)malloc((unsigned)sizeof(struct chentry));
  766.     chlist -> next = newentry;
  767.     }
  768.     else {
  769.         newentry = (struct chentry*)malloc((unsigned)sizeof(struct chentry));
  770.     actlist = newentry;
  771.     }
  772.     /* char not there so add to list */
  773.     newentry -> ch = ch;
  774.     newentry -> id = id;
  775.     newentry -> type = type;
  776.     newentry -> next = NULLCH;
  777.     return TRUE;
  778. }
  779.  
  780.  
  781. WIDGETTYPE widgettype (ptr)
  782. /* given a widget pointer returns the type of widget.
  783.  */
  784. WIDGET    ptr;
  785. {
  786.     struct cmdwid    *clist;
  787.     struct tglwid    *tlist;
  788.     struct lblwid    *llist;
  789.     struct inpwid    *ilist;
  790.  
  791.     /* is it a command widget ? */
  792.     for (clist = cmdlist; clist != NULLCMD; clist = clist -> next)       
  793.         if ((clist != NULLCMD) && (clist -> id == ptr))
  794.             return CMD;
  795.  
  796.     /* is it a toggle widget ? */
  797.     for (tlist = tgllist; tlist != NULLTGL; tlist = tlist -> next)       
  798.         if ((tlist != NULLTGL) && (tlist -> id == ptr))
  799.             return TGL;
  800.  
  801.     /* is it a label widget ? */
  802.     for (llist = lbllist; llist != NULLLBL; llist = llist -> next)       
  803.         if ((llist != NULLLBL) && (llist -> id == ptr))
  804.             return LBL;
  805.  
  806.     /* is in an input widget ? */
  807.     for (ilist = inplist; ilist != NULLINP; ilist = ilist -> next)       
  808.         if ((ilist != NULLINP) && (ilist -> id == ptr))
  809.             return INP;
  810.  
  811.     /* doesn't exist, return error */
  812.     return FALSE;             
  813. }
  814.  
  815. boxwidget (widget, length)
  816. WINDOW    *widget;
  817. int    length;
  818. {
  819.     int i;
  820.  
  821.     wmove (widget, 0, 1);
  822.     for (i=1; i < length; i++)
  823.            waddch (widget, '-');
  824.     wmove (widget, 2, 1);
  825.     for (i=1; i < length; i++)
  826.            waddch (widget, '-');
  827.     mvwaddch (widget, 1, 0, '|');
  828.     mvwaddch (widget, 1, length, '|');
  829.     mvwaddch (widget, 0, 0, '.');
  830.     mvwaddch (widget, 0, length, '.');
  831.     mvwaddch (widget, 2, 0, '`');
  832.     mvwaddch (widget, 2, length, '\'');
  833. }
  834.  
  835. drawcmdwidget (widget, info, ch, length, boolean)
  836. WINDOW    *widget;
  837. char    info[];
  838. char    ch;
  839. int    length;
  840. int    boolean;
  841. {
  842.     boxwidget (widget, length-1);
  843.     wmove (widget, 1, 1);
  844.     wstandout (widget);
  845.     waddch (widget, ch);
  846.     if (!boolean)
  847.         wstandend (widget);
  848.     wprintw (widget, ":%s", info);
  849.     if (boolean)
  850.         wstandend (widget);
  851.     wrefresh (widget);
  852. }
  853.  
  854. drawlblwidget (widget, info, pos, difference, space, boolean)
  855. WINDOW    *widget;
  856. char    info[];
  857. char    pos;
  858. int    difference;
  859. int    space;
  860. int    boolean;
  861. {
  862.     boxwidget (widget, space+1);
  863.  
  864.     /* work out justification */
  865.     if ((pos & LEFTJUST) || (difference == 0))
  866.     wmove (widget, 1, 1);
  867.     else if (pos & RIGHTJUST)
  868.     wmove (widget, 1, 1+difference);
  869.     else if (pos & CENTRE)
  870.     wmove (widget, 1, difference / 2 + 1);
  871.     if (boolean)
  872.         wstandout (widget);
  873.     wprintw (widget, "%s", info);
  874.     if (boolean)
  875.         wstandend (widget);
  876.     wrefresh (widget);
  877. }
  878.   
  879.  
  880. drawtglwidget (widget, info, tgl, toggle, length, boolean)
  881. WINDOW    *widget;
  882. char    info[];
  883. char    tgl[];
  884. char    toggle;
  885. int    length;
  886. int    boolean;
  887. {
  888.     boxwidget (widget, length-1);
  889.     wmove (widget, 1, 1);
  890.     wstandout (widget);
  891.     wprintw (widget, "%c", toggle);
  892.     if (!boolean)
  893.         wstandend (widget);
  894.     wprintw (widget, ":%s:", info);
  895.     if (!boolean)
  896.         wstandout (widget);
  897.     wprintw (widget, "%s", tgl);
  898.     wstandend (widget);
  899.     wrefresh (widget);
  900. }
  901.  
  902. drawinpwidget (widget, info, ch, length, boolean, exec)
  903. WINDOW    *widget;
  904. char    info[];
  905. char    ch;
  906. int    length;
  907. int    boolean;
  908. {
  909.     boxwidget (widget, length-1);
  910.     wmove (widget, 1, 1);
  911.     if (boolean)
  912.         wstandout (widget);
  913.     if (exec)
  914.      wprintw (widget, "%s", info);
  915.     else
  916.         wprintw (widget, "%c:%s", ch, info);
  917.     if (boolean)
  918.         wstandend (widget);
  919.     waddch (widget, '>');
  920.     wrefresh (widget);
  921. }
  922.  
  923. screenrefresh ()
  924. /* clear the screen and redraw all the widgets and the text screen if present */
  925. {
  926.     struct cmdwid *clist;
  927.     struct lblwid *llist;
  928.     struct tglwid *tlist;
  929.     struct inpwid *ilist;
  930.  
  931.     /* clear the entire screen */
  932.     clear();
  933.     refresh();
  934.  
  935.     /* redraw all the command widgets */
  936.     clist = cmdlist;
  937.     while (clist != NULLCMD) {
  938.     touchwin (clist -> widget);
  939.     wrefresh (clist -> widget);
  940.     clist = clist -> next;
  941.     }
  942.  
  943.     /* redraw all the label widgets */
  944.     llist = lbllist;
  945.     while (llist != NULLLBL) {
  946.     touchwin (llist -> widget);
  947.     wrefresh (llist -> widget);
  948.     llist = llist -> next;
  949.     }
  950.  
  951.     /* redraw all the toggle widgets */
  952.     tlist = tgllist;
  953.     while (tlist != NULLTGL) {
  954.     touchwin (tlist -> widget);
  955.     wrefresh (tlist -> widget);
  956.     tlist = tlist -> next;
  957.     }
  958.  
  959.     /* redraw all the input widgets */
  960.     ilist = inplist;
  961.     while (ilist != NULLINP) {
  962.     touchwin (ilist -> widget);
  963.     wrefresh (ilist -> widget);
  964.     ilist = ilist -> next;
  965.     }
  966.  
  967.     /* redraw text window if present */
  968.     if (textwindowdefined) {
  969.     touchwin (screen);
  970.     touchwin (screenbox);
  971.         wrefresh (screenbox);
  972.         wrefresh (screen);
  973.     }
  974. }
  975.  
  976. WIDGET widgetinput ()
  977. /* scan standard input for chars and act on them */
  978. {
  979.     struct cmdwid *list;    
  980.     struct chentry *chlist;
  981.     char      ch;
  982.     int          i;
  983.     int          j;
  984.  
  985.     for (;;)
  986.     {
  987.         ch = getchar ();
  988.  
  989.     if (ch == '\014') {
  990.         screenrefresh ();
  991.         continue;
  992.     }
  993.     
  994.     chlist = actlist;
  995.     while ((chlist != NULLCH) && (chlist -> ch != ch))
  996.         chlist = chlist -> next; 
  997.     
  998.     if (chlist == NULLCH)
  999.         continue;
  1000.  
  1001.         if (chlist -> type == 1) {  /* does char activate a command widget ? */
  1002.             for (list = cmdlist; list != NULLCMD; list = list->next)
  1003.             if (list -> id == chlist -> id)
  1004.             if (list -> active)
  1005.                       return (*(list -> func))();
  1006.         }
  1007.         else if (chlist -> type == 2) /* does char activate a toggle widget ?*/
  1008.             togglewidget (chlist -> id);
  1009.         else 
  1010.             return (getinput (chlist -> id)); /* must activate input widget */    
  1011.     }
  1012. }
  1013.  
  1014.     
  1015. togglewidget (id)
  1016. /* toggle widget given its id */
  1017. WIDGET id;
  1018. {
  1019.     struct tglwid *list;
  1020.     int       i=0;
  1021.     int       x,y;
  1022.     int       pos;
  1023.  
  1024.  
  1025.     list = tgllist;    
  1026.     /* find toggle widget with given id */
  1027.     while (list -> id != id)
  1028.         list = list -> next;
  1029.  
  1030.     if (!list -> active)
  1031.     return;
  1032.  
  1033.     /* increase its toggle value */
  1034.     pos = ++(list -> cur);
  1035.     if (pos == list -> total)   /* do we need to wrap round values */
  1036.     {    pos = 0;
  1037.         list -> cur = 0;
  1038.     }
  1039.  
  1040.     /* output new toggle value */
  1041.     wstandout (list -> widget);
  1042.     mvwaddstr (list -> widget, 1, list -> xtgl, list -> tgl[pos]);
  1043.     wstandend (list -> widget);
  1044.     getyx (list -> widget, y, x);
  1045.     for (; x < list -> length-1; x++)
  1046.         waddch (list -> widget, ' ');
  1047.     wrefresh (list -> widget);
  1048.     if (textwindowdefined)
  1049.         wrefresh (screen);
  1050. }
  1051.  
  1052.  
  1053. int getinput (id)
  1054. /* get input from an input widget and put value into given place */
  1055. WIDGET id;
  1056. {
  1057.     struct inpwid *list;    
  1058.     int       i = 0;
  1059.     int         j;
  1060.     int         cursor = 0;
  1061.     int         index = 0;
  1062.     WINDOW      *widgy;
  1063.     int      max;
  1064.     char     ch = '\0';
  1065.     int         flag = 0;
  1066.     int         sofi;
  1067.  
  1068.     highlight (id);
  1069.     list = inplist;
  1070.     /* find the input widget with the given id */
  1071.     while (list -> id != id)
  1072.         list = list -> next;
  1073.  
  1074.     if (!list -> active)
  1075.     return;
  1076.  
  1077.     widgy = list -> widget;
  1078.     sofi = list -> sofi;
  1079.     max = list -> length - sofi - 1;
  1080.     wmove (widgy, 1, sofi);
  1081.     wrefresh (widgy);
  1082.  
  1083.     /* repeatidly get chars from stdin until carriage return is pressed */
  1084.     while ((ch = getchar()) != '\n') {
  1085.         if ((ch > 31) || (ch == '\025') || (ch == '\014'))
  1086.         {
  1087.         switch (ch) {
  1088.     
  1089.     /* delete ? */
  1090.         case '\177' : if ((!flag) && (cursor > 0)){ /* chars don't spill over */
  1091.                    cursor -= 1;
  1092.                    mvwaddch (widgy, 1, cursor + sofi, ' ');
  1093.                    wmove (widgy, 1, cursor + sofi);
  1094.                    index -= 1;
  1095.                    wrefresh (widgy);
  1096.                    break;
  1097.                   }
  1098.                   else if (cursor > 0){  /* chars spill over */
  1099.                       index -= 1;
  1100.                   if (index == max-1) {
  1101.                       flag = 0;
  1102.                       mvwaddch (widgy, 1, sofi-1, '>');
  1103.                   }
  1104.                   for (j=0; j < max-1; j++)
  1105.                       mvwaddch (widgy, 1, j+sofi, list -> input [index-max+j+1]);
  1106.                       wmove (widgy, 1, cursor + sofi);
  1107.                       wrefresh (widgy);
  1108.                       break;
  1109.                   }
  1110.  
  1111.                   else        /* nothing to delete ! */    
  1112.                   break;
  1113.  
  1114.     /* ^U pressed (delete all) */
  1115.         case '\025' : index = cursor = 0;
  1116.                   wmove (widgy, 1, sofi);
  1117.                   for (j=0; j < max; j++)
  1118.                   waddch (widgy, ' ');
  1119.                   mvwaddch (widgy, 1, sofi-1, '>');
  1120.                   wrefresh (widgy);
  1121.                   break;
  1122.  
  1123.     /* ^L pressed (screen refresh) */
  1124.     case '\014' : screenrefresh ();
  1125.                   wmove (widgy,1,cursor+sofi);
  1126.               wrefresh (widgy);
  1127.               break;
  1128.  
  1129.     /* default = all other chars except remaining control chars */
  1130.         default :    if (index < list -> lofs) {  /* space still remaining ? */
  1131.                  list -> input [index++] = ch;
  1132.                        if (cursor == (max-1)) { /* about to spill over ? */
  1133.                     mvwaddch (widgy, 1, sofi-1, '<');
  1134.                     for (j=0; j < max-2; j++)
  1135.                     mvwaddch (widgy, 1, j+sofi, list ->input [index-max+j+1]);
  1136.                     mvwaddch (widgy, 1, cursor+sofi-1, ch);
  1137.                     flag = 1;
  1138.                     }            
  1139.                     else    /* not spilt over */
  1140.                       mvwaddch (widgy, 1, (cursor++) +sofi, ch);
  1141.                     wrefresh (widgy);
  1142.                     break;
  1143.                       }
  1144.                  else         /* no room left ! */
  1145.                  break;
  1146.                  }
  1147.         }
  1148.         }        
  1149.     /* terminate input */
  1150.     list -> input [index] = '\0';
  1151.  
  1152.     /* clean up input line */
  1153.     wmove (widgy, 1, sofi);
  1154.     for (j=0; j < max; j++)
  1155.         waddch (widgy, ' ');
  1156.     mvwaddch (widgy, 1, sofi-1, '>');
  1157.     wrefresh (widgy);
  1158.     if (textwindowdefined)
  1159.         wrefresh (screen);
  1160.     dehighlight (id);
  1161.     return id;
  1162. }
  1163.  
  1164. WIDGET mkcmdwidget (info, acpt, func, line)
  1165. /* make a new command widget */
  1166. char    info[];
  1167. char    acpt;
  1168. int    (*func)();
  1169. int    line;
  1170. {
  1171.     struct cmdwid     *list;
  1172.     struct cmdwid     *temp;
  1173.     int         length = 0;
  1174.  
  1175.     while (info [length++] != '\0')   /* work out length of command */
  1176.         ;    
  1177.     length += 3;
  1178.     if ((line == 1) || ((length + widx) > COLS-1) || widx == COLS-1)
  1179.         if (widy + 3 == maxwidy) /* go onto next line */
  1180.             return NULLWIDGET;
  1181.     else {
  1182.             widy += 3;
  1183.             widx = 0;          
  1184.     }
  1185.     if (!addtochlist (acpt, curid, 1))  /* activation char in use ? */
  1186.         return NULLWIDGET;
  1187.     
  1188.     /* find end of list and allocate memory for new entry */
  1189.     temp = cmdlist; 
  1190.     if (temp != NULLCMD) {
  1191.         while (temp -> next != NULLCMD)
  1192.             temp = temp -> next;
  1193.         list = (struct cmdwid *)malloc((unsigned)sizeof(struct cmdwid));
  1194.         temp -> next = list;
  1195.     }
  1196.     else {
  1197.         list = (struct cmdwid *)malloc((unsigned)sizeof(struct cmdwid));
  1198.         cmdlist = list;
  1199.     }
  1200.  
  1201.     /* create and display new widget */
  1202.     list -> widget = newwin (3, length, widy, widx);
  1203.  
  1204.     drawcmdwidget (list -> widget, info, acpt, length, FALSE);
  1205.  
  1206.     /* assign information to be withheld */
  1207.     list -> x = widx;
  1208.     list -> y = widy;
  1209.     list -> id = curid;
  1210.     strcpy (list -> msg ,info);
  1211.     list -> func = func;
  1212.     list -> acpt = acpt;
  1213.     list -> length = length;
  1214.     list -> next = NULLCMD;
  1215.     list -> active = TRUE;
  1216.     curid += 1;
  1217.     widx += length;
  1218.     if (textwindowdefined)
  1219.         wrefresh (screen);
  1220.     return (curid-1);
  1221. }
  1222.  
  1223. WIDGET mklblwidget (info, pos, space, line)
  1224. /* make a new label widget */
  1225. char    info[];
  1226. int     pos;
  1227. int     space;
  1228. int     line;
  1229. {
  1230.     struct lblwid    *list;
  1231.     struct lblwid    *temp;
  1232.     int         length = 0;
  1233.     int         difference;
  1234.  
  1235.     if (!((pos & CENTRE) || (pos & LEFTJUST) || (pos & RIGHTJUST)))
  1236.     pos = pos|LEFTJUST;
  1237.  
  1238.     /* calculate length of label widget */
  1239.     while (info [length++] != '\0')    
  1240.         ;    
  1241.     length -= 1;
  1242.     if ((space < length) && (space > 0))    /* not given enough room so error */
  1243.         return NULLWIDGET; 
  1244.     
  1245.     if (space <= 0)
  1246.         if ((line == 1) || (widx == COLS-1))
  1247.         space += COLS - 3;
  1248.     else
  1249.         space += COLS - 3 - widx;
  1250.  
  1251.     difference = space - length;
  1252.  
  1253.     if ((line == 1) || ((space + 2 + widx) > COLS-1) || (widx == COLS-1))
  1254.     /* not enough room on existing line so go onto next */
  1255.         if (widy + 3 == maxwidy)
  1256.             return NULLWIDGET;
  1257.     else {
  1258.         widx = 0;
  1259.         widy += 3;
  1260.      }
  1261.  
  1262.     /* find end of list and alllocate memory for new entry */
  1263.     temp = lbllist;
  1264.     if (temp != NULLLBL) {
  1265.         while (temp -> next != NULLLBL)
  1266.             temp = temp -> next;
  1267.         list = (struct lblwid *)malloc((unsigned)sizeof(struct lblwid));
  1268.         temp -> next = list;
  1269.     }
  1270.     else {
  1271.         list = (struct lblwid *)malloc((unsigned)sizeof(struct lblwid));
  1272.         lbllist = list;
  1273.     }
  1274.  
  1275.     /* create new and display new widget */
  1276.     list -> widget = newwin (3, space+2, widy, widx);
  1277.  
  1278.     drawlblwidget (list -> widget, info, pos, difference, space, !(pos & NOHIGH));
  1279.  
  1280.     /* assign information to be withheld */
  1281.     list -> x = widx;
  1282.     list -> y = widy;
  1283.     list -> id = curid;
  1284.     strcpy (list -> msg ,info);
  1285.     list -> pos = pos;
  1286.     list -> length = space+2;
  1287.     list -> difference = difference;
  1288.     list -> next = NULLLBL;
  1289.     curid += 1;
  1290.     widx += space+2;
  1291.     if (textwindowdefined)
  1292.         wrefresh (screen);
  1293.     return (curid - 1);
  1294. }
  1295.  
  1296. WIDGET mktglwidget (info, num, tgl, toggle, line)
  1297. /* make a new toggle widget */
  1298. char  info[];
  1299. int   num;    
  1300. char  *tgl[10];
  1301. char  toggle;
  1302. int   line;
  1303. {
  1304.     int         length = 0;
  1305.     struct tglwid    *list;
  1306.     struct tglwid    *temp;
  1307.     int         xtgl;
  1308.     int         max = 0;
  1309.     int         i, j, x;
  1310.     
  1311.     /* calculate maximum length of toggle */
  1312.     for (i=0; i < num; i++)  
  1313.         {
  1314.         for (j=0, x=0; tgl[i][j] != '\0'; j++)
  1315.                x++;
  1316.         if ((x-1)>max)
  1317.             max = x-1;
  1318.         }
  1319.     
  1320.     while (info [length++] != '\0') 
  1321.         ;    
  1322.     xtgl = length + 3;
  1323.     length = length + max + 5;
  1324.  
  1325.     if ((line == 1) || ((length + widx) > COLS-1) || (widx == COLS-1))
  1326.         /* not enough room on existing line so go onto next */
  1327.         if (widy + 3 == maxwidy)
  1328.             return NULLWIDGET;
  1329.     else {
  1330.         widx = 0;
  1331.         widy += 3;
  1332.     }
  1333.  
  1334.     /* add char to activation list if not already in use */
  1335.     if (!addtochlist (toggle, curid, 2)) 
  1336.         return NULLWIDGET;
  1337.  
  1338.     /* find end of list and allocate memory for new entry */
  1339.     temp = tgllist;
  1340.     if (temp != NULLTGL) {
  1341.         while (temp -> next != NULLTGL)
  1342.             temp = temp -> next;
  1343.         list = (struct tglwid *)malloc((unsigned)sizeof(struct tglwid));
  1344.         temp -> next = list;
  1345.     }
  1346.     else {
  1347.         list = (struct tglwid *)malloc((unsigned)sizeof(struct tglwid));
  1348.         tgllist = list;
  1349.     }
  1350.  
  1351.     /* create and display new widget */
  1352.     list -> widget = newwin (3, length, widy, widx);
  1353.  
  1354.     drawtglwidget (list -> widget, info, tgl[0], toggle, length, FALSE);
  1355.  
  1356.     /* assign information to be withheld */
  1357.     list -> x = widx;
  1358.     list -> y = widy;
  1359.     list -> id = curid;
  1360.     strcpy (list -> msg ,info);
  1361.     list -> xtgl = xtgl;
  1362.     list -> total = num;
  1363.     for (i=0; i<num; i++) 
  1364.     strcpy (list -> tgl[i], tgl[i]);
  1365.     list -> cur = 0;
  1366.     list -> toggle = toggle;
  1367.     list -> length = length;
  1368.     list -> next = NULLTGL;
  1369.     list -> active = TRUE;
  1370.     curid += 1;
  1371.     widx += length;
  1372.     if (textwindowdefined)
  1373.         wrefresh (screen);
  1374.     return (curid-1);
  1375. }
  1376.  
  1377. WIDGET mkinpwidget (info, acpt, input, lofs, length, line, exec)
  1378. /* make a new input widget */
  1379. char    info[];
  1380. char    acpt;
  1381. char    input[];
  1382. int     lofs;
  1383. int     length;
  1384. int     line;
  1385. int    exec;
  1386. {
  1387.     struct inpwid    *list;
  1388.     struct inpwid    *temp;
  1389.     int            count = 0;
  1390.     int            offset;
  1391.  
  1392.     if (exec)
  1393.           offset = 3;
  1394.     else
  1395.     offset = 5;
  1396.  
  1397.     while (info [count++] != '\0')
  1398.     ;
  1399.  
  1400.     if (length <= 0)
  1401.     if ((line == 1) || (widx == COLS-1))
  1402.         length += COLS-offset-count;
  1403.     else
  1404.         length += COLS-offset-widx-count;
  1405.     length += offset-1+count;
  1406.     if ((line == 1) || ((length + widx) > COLS-1) || (widx == COLS -1))
  1407.         /* if no room on existing line go onto next */
  1408.         if (widy + 3 == maxwidy)
  1409.             return NULLWIDGET;
  1410.     else {
  1411.         widx = 0;
  1412.         widy += 3;
  1413.     }
  1414.  
  1415.     /* add activation char to list if not already in use */
  1416.     if (!addtochlist (acpt, curid, 3)) 
  1417.         return NULLWIDGET;
  1418.  
  1419.     /* find end of list and allocate memory for new entry */
  1420.     temp = inplist;
  1421.     if (temp != NULLINP) {
  1422.         while (temp -> next != NULLINP)
  1423.             temp = temp -> next;
  1424.         list = (struct inpwid *)malloc((unsigned)sizeof(struct inpwid));
  1425.         temp -> next = list;
  1426.     }
  1427.     else {
  1428.         list = (struct inpwid *)malloc((unsigned)sizeof(struct inpwid));
  1429.         inplist = list;
  1430.     }
  1431.  
  1432.     /* create and display new widget */
  1433.     list -> widget = newwin (3, length, widy, widx);
  1434.  
  1435.     drawinpwidget (list -> widget, info, acpt, length, FALSE, exec);
  1436.  
  1437.     /* assign information to be withheld */
  1438.     list -> x = widx;
  1439.     list -> y = widy;
  1440.     list -> id = curid;
  1441.     strcpy (list -> msg ,info);
  1442.     list -> acpt = acpt;
  1443.     list -> input = input;
  1444.     list -> lofs = lofs;
  1445.  
  1446.     if (exec)
  1447.     list -> sofi = count+1;
  1448.     else
  1449.         list -> sofi = count+3;
  1450.  
  1451.     list -> length = length;
  1452.     list -> next = NULLINP;
  1453.     list -> exec = exec;
  1454.     list -> active = TRUE;
  1455.     curid += 1;
  1456.     widx += length;
  1457.     if (textwindowdefined)
  1458.         wrefresh (screen);
  1459.     if (exec)
  1460.     getinput (curid-1);
  1461.     return (curid-1);
  1462. }
  1463.  
  1464. cleartextwindow ()
  1465. {
  1466.     werase (screen);
  1467.     wrefresh (screen);
  1468.     scry = 0;
  1469. }
  1470.  
  1471. report (info)
  1472. /* place given info into data screen */
  1473. char    *info;
  1474. {
  1475.     int i, count = 0;
  1476.  
  1477.     if (textwindowdefined) {
  1478.         if (scry == sizescreg)    /* scroll window if reached bottom */
  1479.         {
  1480.             scroll (screen);
  1481.             scry -= 1;
  1482.         }
  1483.     for (i=0; info[i] != '\0'; i++)
  1484.         if (info[i] == '\n')
  1485.         count += 1;
  1486.  
  1487.         mvwaddstr (screen, scry, 0, info);
  1488.         scry += 1+count;
  1489.         wrefresh (screen);
  1490.     }
  1491. }
  1492.  
  1493. int tsttglwidget (ptr)
  1494. /* return the index value of the current state of the given toggle widget */
  1495. WIDGET ptr;
  1496. {
  1497.     struct tglwid *list;
  1498.     int          i=0;
  1499.  
  1500.     /* locate the record of the given toggle widget pointer */
  1501.     list = tgllist;
  1502.     while ((list != NULLTGL) && (list -> id != ptr)) 
  1503.         list = list -> next;
  1504.  
  1505.     /* if it exists return index value else return error FALSE */
  1506.     if (list -> id == ptr)
  1507.         return list -> cur;
  1508.     else
  1509.         return FALSE;
  1510. }
  1511.  
  1512. deletechentry (ch)
  1513. /* remove the entry from character list for killed widget */
  1514. char ch;
  1515. {
  1516.     struct chentry    *chlist;
  1517.     struct chentry    *previous;
  1518.    
  1519.     chlist = actlist;
  1520.     if (chlist -> ch == ch) {        /* is required entry at head of list ? */
  1521.     actlist = chlist -> next;    
  1522.     free ((char*)chlist);        /* deallocate memory for deleted entry */
  1523.     }
  1524.     else {
  1525.     while (chlist -> ch != ch) {  /* locate required entry in the list */
  1526.         previous = chlist;
  1527.         chlist = chlist -> next;
  1528.     }
  1529.     previous -> next = chlist -> next;  /* remove entry by skiping it */
  1530.     free ((char*)chlist);        /* deallocate memory for deleted entry */
  1531.     }
  1532. }
  1533.  
  1534. killcmdwidget (ptr)
  1535. /* kill a command widget given a valid pointer */
  1536. WIDGET ptr;
  1537. {
  1538.     struct cmdwid    *clist;
  1539.     struct cmdwid    *previous;
  1540.  
  1541.     clist = cmdlist;
  1542.     if (clist -> id == ptr) {         /* required widget at head of list ? */
  1543.     cmdlist = clist -> next;
  1544.     werase (clist -> widget);
  1545.     wrefresh (clist -> widget);
  1546.     delwin (clist -> widget);
  1547.     deletechentry (clist -> acpt);
  1548.     if ((clist -> x + clist -> length) == widx)   /* if last widget added */
  1549.         widx -= clist -> length;              /* pull back widx       */
  1550.     free ((char*)clist);
  1551.     }
  1552.     else {
  1553.     while (clist -> id != ptr) {    /* find widget in list */
  1554.        previous = clist;
  1555.        clist = clist -> next;
  1556.     }
  1557.     previous -> next = clist -> next;   /* skip unrequired widget in list */
  1558.     werase (clist -> widget);
  1559.     wrefresh (clist -> widget);
  1560.     delwin (clist -> widget);
  1561.     deletechentry (clist -> acpt);
  1562.     if ((clist -> x + clist -> length) == widx)   /* if last widget added */
  1563.         widx -= clist -> length;              /* pull back widx       */
  1564.     free ((char*)clist);
  1565.     }
  1566. }
  1567.  
  1568. killlblwidget (ptr)
  1569. /* kill label widget given a valid pointer */
  1570. WIDGET ptr;
  1571. {
  1572.     struct lblwid    *clist;
  1573.     struct lblwid    *previous;
  1574.  
  1575.     clist = lbllist;
  1576.     if (clist -> id == ptr) {         /* is widget at head of list ? */
  1577.     lbllist = clist -> next;
  1578.     werase (clist -> widget);
  1579.     wrefresh (clist -> widget);
  1580.     delwin (clist -> widget);
  1581.     if ((clist -> x + clist -> length) == widx)  /* pull back widx if */
  1582.         widx -= clist -> length;             /* last widget added */
  1583.     free ((char*)clist);
  1584.     }
  1585.     else {
  1586.     while (clist -> id != ptr) {    /* find widget in linked list */
  1587.        previous = clist;
  1588.        clist = clist -> next;
  1589.     }
  1590.     previous -> next = clist -> next;   /* skip widget in list */
  1591.     werase (clist -> widget);
  1592.     wrefresh (clist -> widget);
  1593.     delwin (clist -> widget);
  1594.     if ((clist -> x + clist -> length) == widx)  /* pull back widx if */
  1595.         widx -= clist -> length;             /* last widget added */
  1596.     free ((char*)clist);
  1597.     }
  1598. }
  1599.  
  1600. killtglwidget (ptr)
  1601. /* kill toggle widget given a valid pointer */
  1602. WIDGET ptr;
  1603. {
  1604.     struct tglwid    *clist;
  1605.     struct tglwid    *previous;
  1606.  
  1607.     clist = tgllist;
  1608.     if (clist -> id == ptr) {       /* is widget at head of list ? */
  1609.     tgllist = clist -> next;
  1610.     werase (clist -> widget);
  1611.     wrefresh (clist -> widget);
  1612.     delwin (clist -> widget);
  1613.     deletechentry (clist -> toggle);
  1614.     if ((clist -> x + clist -> length) == widx)  /* pull back widx if */
  1615.         widx -= clist -> length;             /* last widget added */
  1616.     free ((char*)clist);
  1617.     }
  1618.     else {
  1619.     while (clist -> id != ptr) {    /* find widget in linked list */
  1620.        previous = clist;
  1621.        clist = clist -> next;
  1622.     }
  1623.     previous -> next = clist -> next;   /* skip widget in list */
  1624.     werase (clist -> widget);
  1625.     wrefresh (clist -> widget);
  1626.     delwin (clist -> widget);
  1627.     deletechentry (clist -> toggle);
  1628.     if ((clist -> x + clist -> length) == widx)   /* pull back widx if */
  1629.         widx -= clist -> length;              /* last widget added */
  1630.     free ((char*)clist);
  1631.     }
  1632. }
  1633.  
  1634. killinpwidget (ptr)
  1635. /* kill an input widget given a valid pointer */
  1636. WIDGET ptr;
  1637. {
  1638.     struct inpwid    *clist;
  1639.     struct inpwid    *previous;
  1640.  
  1641.     clist = inplist;
  1642.     if (clist -> id == ptr) {        /* is widget at head of list ? */
  1643.     inplist = clist -> next;
  1644.     werase (clist -> widget);
  1645.     wrefresh (clist -> widget);
  1646.     delwin (clist -> widget);
  1647.     deletechentry (clist -> acpt);
  1648.     if ((clist -> x + clist -> length) == widx)   /* pull back widx if */
  1649.         widx -= clist -> length;              /* last widget added */
  1650.     free ((char*)clist);
  1651.     }
  1652.     else {
  1653.     while (clist -> id != ptr) {   /* locate widget in linked list */
  1654.        previous = clist;
  1655.        clist = clist -> next;
  1656.     }
  1657.     previous -> next = clist -> next;   /* skip entry in linked list */
  1658.     werase (clist -> widget);
  1659.     wrefresh (clist -> widget);
  1660.     delwin (clist -> widget);
  1661.     deletechentry (clist -> acpt);
  1662.     if ((clist -> x + clist -> length) == widx)   /* pull back widx if */
  1663.         widx -= clist -> length;              /* last widget added */
  1664.     free ((char*)clist);
  1665.     }
  1666. }
  1667.     
  1668. int killwidget (ptr)
  1669. /* kills the widget identified by ptr */
  1670. WIDGET ptr;
  1671. {
  1672.     switch (widgettype (ptr)) {
  1673.         case CMD : killcmdwidget (ptr);    /* command widget */
  1674.          home ();
  1675.          return TRUE;
  1676.     case TGL : killtglwidget (ptr);    /* toggle widget */
  1677.          home ();
  1678.          return TRUE;
  1679.     case LBL : killlblwidget (ptr);    /* label widget */
  1680.          home ();
  1681.          return TRUE;
  1682.     case INP : killinpwidget (ptr);    /* input widget */
  1683.          home ();
  1684.          return TRUE;
  1685.     case FALSE : return FALSE;           /* doesn't exist */
  1686.     }
  1687. }
  1688.  
  1689. int chactive (ptr, boolean, blank)
  1690. /* given a widget ptr and a boolean value will activate/deactivate a widget */
  1691. WIDGET ptr;
  1692. int boolean;
  1693. int blank;
  1694. {
  1695.     struct cmdwid *clist;
  1696.     struct tglwid *tlist;
  1697.     struct inpwid *ilist;
  1698.     int          i;
  1699.  
  1700.     switch (widgettype (ptr)) {
  1701.     case CMD: for (clist = cmdlist; clist != NULLCMD; clist = clist -> next)
  1702.           if ((clist != NULLCMD) && (clist -> id == ptr)) {
  1703.             if ((!boolean) && (blank)) {
  1704.                 wmove (clist->widget, 1, 1);
  1705.                 for (i=0; i < clist->length-2; i++)
  1706.                 waddch (clist->widget, ' ');
  1707.                 wrefresh (clist->widget);
  1708.             }
  1709.               if (textwindowdefined)
  1710.                     wrefresh (screen);
  1711.             return(clist -> active = boolean);
  1712.           }
  1713.           break;
  1714.     case TGL: for (tlist = tgllist; tlist != NULLTGL; tlist = tlist -> next)
  1715.           if ((tlist != NULLTGL) && (tlist -> id == ptr)) {
  1716.             if ((!boolean) && (blank)) {
  1717.                 wmove (tlist->widget, 1, 1);
  1718.                 for (i=0; i < tlist->length-2; i++)
  1719.                 waddch (tlist->widget, ' ');
  1720.                 wrefresh (tlist->widget);
  1721.             }
  1722.               if (textwindowdefined)
  1723.                     wrefresh (screen);
  1724.             return(tlist -> active = boolean);
  1725.           }
  1726.           break;
  1727.     case INP: for (ilist = inplist; ilist != NULLINP; ilist = ilist -> next)
  1728.           if ((ilist != NULLINP) && (ilist -> id == ptr)) {
  1729.             if ((!boolean) && (blank)) {
  1730.                 wmove (ilist->widget, 1, 1);
  1731.                 for (i=0; i < ilist->length-2; i++)
  1732.                 waddch (ilist->widget, ' ');
  1733.                 wrefresh (ilist->widget);
  1734.             }
  1735.               if (textwindowdefined)
  1736.                     wrefresh (screen);
  1737.             return (ilist -> active = boolean);
  1738.           }
  1739.           break;
  1740.     default : return FALSE;
  1741.     }
  1742. }
  1743.  
  1744. int activate (ptr)
  1745. /* reactivate a widget given its ptr */
  1746. WIDGET ptr;
  1747. {
  1748.     int boolean;
  1749.  
  1750.     boolean = (chactive (ptr, TRUE));
  1751.     light (ptr, FALSE);
  1752.     return boolean;
  1753. }
  1754.  
  1755. int deactivate (ptr, blank)
  1756. /* deactivates a widget given its ptr */
  1757. WIDGET ptr;
  1758. int    blank;
  1759. {
  1760.     return (chactive (ptr, FALSE, blank));
  1761. }
  1762.  
  1763. int light (ptr, boolean)
  1764. /* will highlight or dehighlight a given widget */
  1765. WIDGET ptr;
  1766. int boolean;
  1767. {
  1768.     struct cmdwid *clist;
  1769.     struct tglwid *tlist;
  1770.     struct lblwid *llist;
  1771.     struct inpwid *ilist;
  1772.  
  1773.     switch (widgettype (ptr)) {
  1774.     case CMD: for (clist = cmdlist; clist != NULLCMD; clist = clist -> next)
  1775.           if ((clist != NULLCMD) && (clist -> id == ptr)) {
  1776.               if (clist -> active)
  1777.                       drawcmdwidget (clist->widget,clist->msg,clist->acpt,clist->length,boolean);
  1778.           if (textwindowdefined)
  1779.                 wrefresh (screen);
  1780.           return (clist -> active);
  1781.           }
  1782.           break;
  1783.  
  1784.     case TGL: for (tlist = tgllist; tlist != NULLTGL; tlist = tlist -> next)
  1785.           if ((tlist != NULLTGL) && (tlist -> id == ptr)) {
  1786.               if (tlist -> active)
  1787.                     drawtglwidget (tlist->widget,tlist->msg,tlist->tgl[tlist->cur],tlist->toggle,tlist->length,boolean);
  1788.           if (textwindowdefined)
  1789.                 wrefresh (screen);
  1790.           return (tlist -> active);
  1791.           }
  1792.           break;
  1793.  
  1794.     case LBL: for (llist = lbllist; llist != NULLLBL; llist = llist -> next)
  1795.           if ((llist != NULLLBL) && (llist -> id == ptr))
  1796.               drawlblwidget (llist->widget,llist->msg,llist->pos,llist->difference,llist->length-2,boolean);
  1797.           if (textwindowdefined)
  1798.                 wrefresh (screen);
  1799.           return TRUE;
  1800.           break;
  1801.  
  1802.     case INP: for (ilist = inplist; ilist != NULLINP; ilist = ilist -> next)
  1803.           if ((ilist != NULLINP) && (ilist -> id == ptr)) {
  1804.               if (ilist -> active)
  1805.                     drawinpwidget (ilist->widget,ilist->msg,ilist->acpt,ilist->length,boolean,ilist->exec);
  1806.           if (textwindowdefined)
  1807.                 wrefresh (screen);
  1808.           return (ilist -> active);
  1809.           }
  1810.           break;
  1811.  
  1812.     }
  1813.     return FALSE;
  1814. }
  1815.  
  1816. int highlight (ptr)
  1817. /* highlights the given ACTIVE widget */
  1818. WIDGET ptr;
  1819. {
  1820.     return (light (ptr, TRUE));
  1821. }
  1822.  
  1823. int dehighlight (ptr)
  1824. /* dehighlights the given ACTIVE widget */
  1825. WIDGET ptr;
  1826. {
  1827.     return (light (ptr, FALSE));
  1828. }
  1829.  
  1830. home ()
  1831. /* scans the current state of the screen and places the x,y cursor coordinates
  1832.    at the end of widget furthest down and to the right */
  1833. {
  1834.     struct cmdwid *clist = cmdlist;
  1835.     struct lblwid *llist = lbllist;
  1836.     struct tglwid *tlist = tgllist;
  1837.     struct inpwid *ilist = inplist;
  1838.     int           x, y;
  1839.  
  1840.     x = y = 0;
  1841.  
  1842.     /* look through command widgets */
  1843.     while (clist != NULLCMD) {
  1844.     if (clist -> y > y) {
  1845.         y = clist -> y;
  1846.         x = clist->x + clist->length;
  1847.     }
  1848.     else if ((clist->x + clist->length > x) && (clist -> y == y)) {
  1849.         x = clist->x + clist->length;
  1850. }
  1851.        clist = clist -> next;
  1852.     }
  1853.  
  1854.     /* look through toggle widgets */
  1855.     while (tlist != NULLTGL) {
  1856.     if (tlist -> y > y) {
  1857.         y = tlist -> y;
  1858.         x = tlist->x + tlist->length;
  1859.     }
  1860.     else if ((tlist->x + tlist->length > x) && (tlist -> y == y)) {
  1861.         x = tlist->x + tlist->length;
  1862. }
  1863.     tlist = tlist -> next;
  1864.     }
  1865.  
  1866.     /* look through label widgets */
  1867.     while (llist != NULLLBL) {
  1868.     if (llist -> y > y) {
  1869.         y = llist -> y;
  1870.         x = llist->x + llist->length;
  1871.     }
  1872.     else if ((llist->x + llist->length > x) && (llist -> y == y)) {
  1873.         x = llist->x + llist->length;
  1874. }
  1875.     llist = llist -> next;
  1876.     }
  1877.  
  1878.     /* look through input widgets */
  1879.     while (ilist != NULLINP) {
  1880.     if (ilist -> y > y) {
  1881.         y = ilist -> y;
  1882.         x = ilist->x + ilist->length;
  1883.     }
  1884.     else if ((ilist->x + ilist->length > x) && (ilist -> y == y)) {
  1885.         x = ilist->x + ilist->length;
  1886. }
  1887.     ilist = ilist -> next;
  1888.     }
  1889.    
  1890.     /* update screen x,y coordinates */
  1891.     widx = x;
  1892.     widy = y;
  1893. }
  1894.  
  1895. int changelblwidget (ptr, info, pos)
  1896. WIDGET ptr;
  1897. char   info[];
  1898. int    pos;
  1899. {
  1900.     struct lblwid *list = lbllist;
  1901.     int          length = 0;
  1902.  
  1903.     while ((list != NULLLBL) && (list->id != ptr))
  1904.     list = list -> next;
  1905.  
  1906.     if (list == NULLLBL)
  1907.     return FALSE;
  1908.  
  1909.     if (!((pos & CENTRE) || (pos & LEFTJUST) || (pos & RIGHTJUST)))
  1910.     pos = pos|LEFTJUST;
  1911.  
  1912.     /* calculate length of label widget */
  1913.     while (info [length++] != '\0')    
  1914.         ;    
  1915.     length -= 1;
  1916.     if (list->length-2 < length) /* not given enough room so error */
  1917.         return FALSE;
  1918.     
  1919.     list -> difference = list->length-2 - length;
  1920.  
  1921.     strcpy (list -> msg, info);
  1922.     list -> pos = pos;
  1923.     werase (list->widget);
  1924.     drawlblwidget (list->widget,info,pos,list->difference,list->length-2,!(pos & NOHIGH));
  1925.  
  1926.     if (textwindowdefined)
  1927.     wrefresh (screen);
  1928.     return (TRUE);
  1929. }
  1930.  
  1931. endwidgets ()
  1932. /* tidy up at the end */
  1933. {
  1934.     struct cmdwid *clist = cmdlist;
  1935.     struct lblwid *llist = lbllist;
  1936.     struct tglwid *tlist = tgllist;
  1937.     struct inpwid *ilist = inplist;
  1938.  
  1939.     while (clist != NULLCMD) {
  1940.     killcmdwidget (clist -> id);
  1941.         clist = cmdlist;
  1942.     }
  1943.  
  1944.     while (llist != NULLLBL) {
  1945.     killlblwidget (llist -> id);
  1946.     llist = lbllist;
  1947.     }
  1948.  
  1949.     while (tlist != NULLTGL) {
  1950.     killtglwidget (tlist -> id);
  1951.     tlist = tgllist;
  1952.     }
  1953.  
  1954.     while (ilist != NULLINP) {
  1955.     killinpwidget (ilist -> id);
  1956.     ilist = inplist;
  1957.     }
  1958.  
  1959.     killtextwindow ();
  1960.     endwin ();
  1961.     exit (0);
  1962. }
  1963.  
  1964. killtextwindow ()
  1965. /* destroy screen and any borders */
  1966. {
  1967.     if (textwindowdefined) {
  1968.     werase (screen);
  1969.     wrefresh (screen);
  1970.     delwin (screen);
  1971.     textwindowdefined = FALSE;
  1972.     if ((screenborder & VERTICAL) && (screenborder & HORIZONTAL)) {
  1973.         werase (screenbox);
  1974.         wrefresh (screenbox);
  1975.         delwin (screenbox);
  1976.      }
  1977.     else if ((screenborder & VERTICAL) || (screenborder & HORIZONTAL)) {
  1978.         werase (edge1);
  1979.         werase (edge2);
  1980.         wrefresh (edge1);
  1981.         wrefresh (edge2);
  1982.         delwin (edge1);
  1983.         delwin (edge2);
  1984.         }
  1985.     maxwidy = LINES - 2;
  1986.     screenborder = 0;
  1987.     }
  1988. }
  1989. SHAR_EOF
  1990. if test 34817 -ne `wc -c < 'widgetlib.c'`
  1991. then
  1992.     echo 'Shar: error transmitting 'widgetlib.c' (should have been  34817 charcaters)'
  1993. fi
  1994. fi
  1995. echo 'Shar: extracting 'wpage.c' ( 3218 characters)'
  1996. if test -f 'wpage.c'
  1997. then
  1998.     echo "Shar: will not overwrite existing file 'wpage.c'"
  1999. else
  2000.     cat << \SHAR_EOF > 'wpage.c'
  2001. /*****************************************************************************
  2002. /*  FILE:        wpage.c
  2003. /*  DATE:        August 1988.
  2004. /*  AUTHOR:        Richard A. Culshaw.
  2005. /*  DESCRIPTION:    A small demonstration program using the widgets.
  2006. /* DISCLAIMER:        This file is deemed to be public-domain, on the simple
  2007. /*            provisos that this section remains in this file and
  2008. /*            that code using it do not do so for monetary gain.
  2009. /*            Neither the author, nor the authors employees at the
  2010. /*            time of developing this code, accept any liability or
  2011. /*            responsibility for the use, abuse or misuse of this
  2012. /*            code.
  2013. /*****************************************************************************/
  2014.  
  2015. #include <widget.h>
  2016.  
  2017. WIDGET    title, nlcmd, npcmd, qcmd, finput, gfile, frac;
  2018. char    filename[14];
  2019. char    string[20];
  2020. int    nolines;
  2021. int    filepresent;
  2022. FILE    *f;
  2023. long    size, ftell();
  2024.  
  2025. int readline ()
  2026. {
  2027.     int   i;
  2028.     int      space;
  2029.     char  buffer [80];
  2030.     int   count;
  2031.     int   ch;
  2032.  
  2033.     count = 0;
  2034.       while ((count < 79) && (ch = getc(f)) && (ch != '\n') && (ch != EOF))
  2035.         if (ch == '\t') {
  2036.         space = 8 - count % 8;
  2037.         for (i=0; i<space; i++)
  2038.             buffer [count++] = ' ';
  2039.          }
  2040.         else
  2041.             buffer [count++] = ch;
  2042.         buffer [count] = '\0';
  2043.         if ((count > 0) || (ch == '\n'));
  2044.         report (buffer);
  2045.     return (ch); 
  2046. }
  2047.  
  2048. changefrac ()
  2049. {
  2050.     long  cur;
  2051.     char  data[5];
  2052.  
  2053.     cur = ftell (f);
  2054.     sprintf (data, "%ld%%", cur*100L/size);
  2055.     changelblwidget (frac, data, RIGHTJUST|NOHIGH);
  2056. }
  2057.  
  2058.  
  2059. nextline ()
  2060. {
  2061.     int ch;
  2062.  
  2063.     highlight (nlcmd);
  2064.     ch = readline ();
  2065.     dehighlight (nlcmd);
  2066.     if (ch == EOF) {
  2067.     deactivate (npcmd, BLANK);
  2068.     deactivate (nlcmd, BLANK);
  2069.     }
  2070.     changefrac ();
  2071.     widgetinput ();
  2072. }
  2073.  
  2074. nextpage ()
  2075. {
  2076.     int   line  = 0;
  2077.     int      ch;
  2078.  
  2079.     highlight (npcmd);
  2080.     cleartextwindow ();
  2081.  
  2082.     while ((line++ != nolines) && ((ch = readline()) != EOF)) 
  2083.     ;
  2084.     
  2085.     dehighlight (npcmd);
  2086.     if (ch == EOF) {
  2087.     deactivate (npcmd, BLANK);
  2088.     deactivate (nlcmd, BLANK);
  2089.     }
  2090.  
  2091.     changefrac ();
  2092.     widgetinput ();
  2093. }
  2094.  
  2095. quit ()
  2096. {
  2097.     endwidgets ();
  2098. }
  2099.  
  2100. getfile ()
  2101. {
  2102.     int i;
  2103.  
  2104.     if (!filepresent) {
  2105.         highlight (gfile);
  2106.         killwidget (title);
  2107.         changelblwidget (frac, "", RIGHTJUST|NOHIGH);
  2108.         finput = mkinpwidget ("file", NULL, filename, 14, 0, 0, EXEC);
  2109.         killwidget (finput);
  2110.     }
  2111.     else
  2112.     filepresent = FALSE;
  2113.     for (i=5; i<=20; i++)
  2114.        string [i] = filename [i-5]; 
  2115.     dehighlight (gfile);
  2116.     f = fopen (filename, "r");
  2117.     if (f == NULL) {
  2118.     cleartextwindow ();    
  2119.     report ("File does not exist. Try again");
  2120.     getfile ();
  2121.     }
  2122.     title = mklblwidget (string, CENTRE, 0, 0);
  2123.     fseek (f, 0L, 2);
  2124.     size = ftell (f);
  2125.     rewind (f);
  2126.     activate (nlcmd);
  2127.     activate (npcmd);
  2128.     nextpage ();
  2129. }
  2130.  
  2131. main (argc, argv)
  2132. int    argc;
  2133. char    *argv[];
  2134. {
  2135.     initialisewidgets ();
  2136.     if (argc > 1) {
  2137.     strcpy (filename, argv[1]);
  2138.     filepresent = TRUE;
  2139.     }
  2140.     strcpy (string, "File=");
  2141.     qcmd = mkcmdwidget ("Quit", 'q', quit, 0);
  2142.     nlcmd = mkcmdwidget ("Next line", 'n', nextline, 0);
  2143.     npcmd = mkcmdwidget ("Next page", 'N', nextpage, 0);
  2144.     gfile = mkcmdwidget ("Get file", 'f', getfile, 0);
  2145.     frac = mklblwidget ("", CENTRE, 4, 0);
  2146.     nolines = opentextwindow (0, HORIZONTAL);
  2147.     getfile ();
  2148. }    
  2149. SHAR_EOF
  2150. if test 3218 -ne `wc -c < 'wpage.c'`
  2151. then
  2152.     echo 'Shar: error transmitting 'wpage.c' (should have been  3218 charcaters)'
  2153. fi
  2154. fi
  2155.